#pragma once

#include "Resource.h"

#include "StickyTweetsAppXP.h"
#include "TwitterStatus.h"

#define STM_TASKBAR    WM_USER      //< Taskbar notification clicked
#define STM_ASYNC     (WM_USER + 1) //< Async operation has completed: WPARAM = request's HINTERNET
#define STM_ASYNC_ERR (WM_USER + 2) //< Async operation has failed: WPARAM = request's HINTERNET

extern HINSTANCE hInst;       //< Application instance

extern HWND hWndStickyTweets; //< Our main window
extern HWND hWndRefresh;      //< Our Refresh SysLink control
extern HWND hWndSettings;     //< Our Settings SysLink control
extern HWND hWndSwitchUser;   //< Our Switch User SysLink control
extern HWND hWndUpgrade;      //< Our Upgrade SysLink control
extern HWND hWndError;        //< Our STATIC control for errors and warnings
extern HWND hWndCharCounter;  //< Our STATIC control for the character count
extern HWND hWndCancel;       //< Cancel tweet BUTTON
extern HWND hWndStatus;       //< Our EDIT control
extern HWND hWndUpdate;       //< Our BUTTON control
extern HWND hWndSearchEdit;   //< Our Search EDIT control
extern HWND hWndSearchButton; //< Search!
extern HWND hWndFollow;       //< Follow BUTTON
extern HWND hWndFilter;       //< Filter BUTTON
extern HWND hWndTweetsChild;  //< Child window for tweet display

typedef enum StickyTweetsPageE
{
  CurrentTimeline,
  DirectPage,
  UserTimeline,
  SearchPage,
  NumPages
} StickyTweetsPage;

extern StickyTweetsPage stPage;

typedef enum XmlSchemaE
{
  TwitterXml,
  AtomXml
} XmlSchema;

BOOL InitInstance(HINSTANCE, int);

LRESULT CALLBACK StickyTweetsWindow(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK TweetsChild(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

/*!
 * \brief WinInet async callback
 */
VOID CALLBACK AsyncCallback(HINTERNET hInternet, __in DWORD_PTR pContext, DWORD internetStatus, __in_bcount(dwStatusInformationLength)LPVOID pStatusInformation, DWORD statusInformationLength);

VOID StickyTweetsWindow_Create(HWND hWnd);
VOID StickyTweetsWindow_Activate();
VOID StickyTweetsWindow_Size(WORD width, WORD height);
VOID StickyTweetsWindow_Paint(HDC hdc, const PAINTSTRUCT& ps);
VOID StickyTweetsWindow_PaintCurrentTimeline(StickyTweetsAppXP& app, Graphics& graphics, const RectF& invalidRect);
VOID StickyTweetsWindow_PaintDirectPage(StickyTweetsAppXP& app, Graphics& graphics, const RectF& invalidRect);
VOID StickyTweetsWindow_PaintUserTimeline(StickyTweetsAppXP& app, Graphics& graphics, const RectF& invalidRect);
VOID StickyTweetsWindow_PaintSearch(StickyTweetsAppXP& app, Graphics& graphics, const RectF& invalidRect);
VOID StickyTweetsWindow_PaintSettings(StickyTweetsAppXP& app, Graphics& graphics, const RectF& invalidRect);
VOID StickyTweetsWindow_KeyDown(UINT virtualKey, INT repeat, UINT flags);
VOID StickyTweetsWindow_MouseMove(POINTS p);
LRESULT StickyTweetsWindow_MouseWheel(HWND hWnd, INT xPos, INT yPos, INT delta, UINT fwKeys);
VOID StickyTweetsWindow_LButtonDown(POINTS p);
BOOL StickyTweetsWindow_Command(HWND hWnd, WORD id, WORD commandEvent);
VOID StickyTweetsWindow_Char(UINT virtualKey);
VOID StickyTweetsWindow_Notify(LPNMHDR header, PNMLINK link);
VOID StickyTweetsWindow_Timer(HWND hWnd, UINT timerId);
VOID StickyTweetsWindow_Taskbar(HWND hWnd, UINT taskbarMessage);
VOID StickyTweetsWindow_Async(HINTERNET hRequest);
VOID StickyTweetsWindow_Async_Failed(HINTERNET hRequest);

VOID RefreshLink_Notify(VOID);
VOID SettingsLink_Notify(VOID);
VOID SwitchUserLink_Notify();

VOID FollowButton_Click(VOID);
VOID FilterButton_Click(VOID);

VOID TweetsChild_Paint(StickyTweetsAppXP& app, Graphics& graphics, const RectF& invalidRect, INT minIdx, INT maxIdx);
VOID TweetsChild_MouseMove(POINTS p);
VOID TweetsChild_LButtonDown(POINTS p);
VOID TweetsChild_VScroll(UINT code, INT position);

/*!
 * \brief   Check for updates and show the Upgrade link if one is available
 * \returns true if there is an upgrade available
 */
bool CheckForUpgrade();

/*!
 * \brief   Display or clear a status message to the user
 */
VOID DisplayStStatus(HWND hWnd, StickyTweetsStatus status);

/*!
 * \brief   Empty all RectF values from all tweets
 */
VOID EmptyRects(CAtlList<TwitterStatus>& tweetList);

/*!
 * \brief   Remove 'filtered' tweets from a list
 */
VOID FilterTimeline(CAtlList<TwitterStatus>& tweetList);

/*!
 * \brief Extract the immediate recipient for the current message, i.e., "@c* "
 */
CString GetRecipient(void);

/*!
 * \brief   Get scroll bar track position
 *
 * Thanks Raymond Chen.
 */
UINT GetTrackPosition(HWND hWnd, INT scrollBar);

/*!
 * \brief   Delete all stored images
 */
void DeleteImageMap();

/*!
 * \brief   Check for something fun and load it
 */
bool IsSeasonal();

/*!
 * \brief   Move the link commands around (and the search box) based on window size
 */
void MoveLinks(WORD width, WORD height);

/*!
 * \breif   Delete images no longer in use
 */
void PruneImageMap();

/*!
 * \brief   Does not query for new XML but may download images
 */
VOID RedrawCurrentPage(VOID);

/*!
 * \brief   Retrieve current timeline from Twitter
 */
StickyTweetsStatus RefreshCurrentTimeline(VOID);

/*!
 * \brief   An async current timeline request has completed
 */
StickyTweetsStatus RefreshCurrentTimelineComplete(RequestContext* pRequest);

/*!
 * \brief   An async mention request has completed
 */
StickyTweetsStatus RefreshMentionsComplete(RequestContext* pRequest);

/*!
 * \brief   Retrieve users direct messages
 */
StickyTweetsStatus RefreshDirectPage(VOID);

/*!
 * \brief   An async DMs request has completed
 */
StickyTweetsStatus RefreshDirectComplete(RequestContext* pRequest);

/*!
 * \brief   An async sent DMs request has completed
 */
StickyTweetsStatus RefreshSentDirectComplete(RequestContext* pRequest);

/*!
 * \brief   Retrieve user timeline from Twitter
 *
 * \param   screenName - Intentionally not a reference
 */
StickyTweetsStatus RefreshUserTimeline(CString screenName);

/*!
 * \brief   An async user timeline request has completed
 */
StickyTweetsStatus RefreshUserTimelineComplete(RequestContext* pRequest);

/*!
 * \brief   Search Twitter
 */
StickyTweetsStatus RefreshSearch(CString query);

/*!
 * \brief   An search request has completed
 */
StickyTweetsStatus RefreshSearchComplete(RequestContext* pRequest);

/*!
 * \brief   Resize child window
 */
VOID ResizeTweetsChild(VOID);

/*!
 * \brief   Scroll the tweet display by an amount
 *
 * Thanks Raymond Chen.
 */
VOID ScrollBy(INT delta);

/*!
 * \brief   Scroll the tweet display to the given position
 *
 * Thanks Raymond Chen.
 */
VOID ScrollTo(INT pos);

/*!
 * \brief   Grab user input and call RefreshSearch
 */
VOID Search();

/*!
 * \brief   Sets the window to display the current timeline
 */
VOID ShowCurrentTimeline(bool redraw = false);

/*!
 * \brief   Sets the window to display direct messages
 */
VOID ShowDirectPage(bool redraw = false);

/*!
 * \brief   Sets the window to display the user timleine
 */
VOID ShowUserTimeline(bool redraw = false);

/*!
 * \brief   Sets the window to display the search results page
 */
VOID ShowSearchPage(bool redraw = false);

/*!
 * \brief   Call this to show the StickyTweets window when requested
 *
 * Does nothing if StickyTweets is the foreground window.
 */
VOID ShowStickyTweets(VOID);

/*!
 * \brief   Stores the top tweet ID if there is one
 * \param   invalidateCheck - TRUE to perform invalidate check, FALSE if you want to invalide yourself later
 * \returns TRUE if the last viewed ID was updated
 */
BOOL UpdateLastViewed(BOOL invalidateCheck = TRUE);

/*!
 *\brief    Assumes the current tweet list has updated UI and sets scrollData
 */
void UpdateScrollData(void);

/*!
 * \brief   Fix the counter and other misc
 */
VOID UpdateStatusControls(bool clearError = false);

/*!
 * \brief   Called by either the Update button click or hitting Enter on the status box
 */
VOID UpdateStatus(HWND hWnd);

/*!
 * \brief   Fill the global timelineUI list with elements based on the passed in XML
 */
int UpdateTimelineUI(const CString& timelineXml, CAtlList<TwitterStatus>& timelineUI, XmlSchema xmlSchema = TwitterXml);
